#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

#define BUFFER_SIZE 255

int close_socket_in_parent=1;
// 生肖数组
const char* zodiacAnimals[] = {
    "rat", "ox", "tiger", "rabbit", "dragon", "snake", "horse", "goat", "monkey", "rooster", "dog", "pig"
};

// 根据年份（端口号）计算生肖
const char* getZodiac(int year) {
    int index = (year - 4) % 12;
    return zodiacAnimals[index];
}

int main(int argc, char *argv[]) {
    int server_sock_listen, server_sock_data;
    struct sockaddr_in server_addr;
    char recv_msg[BUFFER_SIZE];
    char send_msg[BUFFER_SIZE];
    int port;
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);

    // 检查命令行参数数量
    if (argc != 3) {
       fprintf(stderr, "Usage: %s <port> <0/1>\n", argv[0]);
        fprintf(stderr, "0: 不在父进程中关闭 socket\n");
        fprintf(stderr, "1: 在父进程中关闭 socket (默认)\n");
        return 1;
    }

    // 将命令行参数转换为整数
    port = atoi(argv[1]);
    if (port <= 0 || port > 65535) {
        fprintf(stderr, "Invalid port number: %s\n", argv[1]);
        return 1;
    }
    close_socket_in_parent = atoi(argv[2]); // 根据命令行参数决定是否关闭 socket
    /* 创建socket */
    server_sock_listen = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock_listen == -1) {
        perror("socket");
        return 1;
    }

    /* 指定服务器地址 */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons((uint16_t)port); // 使用用户输入的端口号
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY表示本机所有IP地址
    memset(&server_addr.sin_zero, 0, sizeof(server_addr.sin_zero)); // 零填充

    /* 绑定socket与地址 */
    if (bind(server_sock_listen, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        close(server_sock_listen);
        return 1;
    }

    /* 监听socket */
    if (listen(server_sock_listen, 5) == -1) { // 可以同时处理的连接队列长度设置为5
        perror("listen");
        close(server_sock_listen);
        return 1;
    }

    printf("Server listening on port %d...\n", port);

    while (1) {
        server_sock_data = accept(server_sock_listen, (struct sockaddr*)&client_addr,&client_addr_len);
        if (server_sock_data == -1) {
            perror("accept error");
            continue; // 如果接受连接失败，继续监听下一个连接
        }
        //获取客户端IP地址
                char client_ip[INET_ADDRSTRLEN];
                inet_ntop(AF_INET,&client_addr.sin_addr,client_ip,sizeof(client_ip));
                printf("From client IP: %s:%d\n",client_ip,ntohs(client_addr.sin_port));
        pid_t pid = fork();
        if (pid == -1) {
            perror("fork");
            close(server_sock_data);
            continue;
        }

        if (pid == 0) { // 子进程
            close(server_sock_listen); // 子进程不需要监听socket
            while (1) {
                /* 接收并显示消息 */
                memset(recv_msg, 0, sizeof(recv_msg)); // 接收数组置零
                int recv_len = recv(server_sock_data, recv_msg, sizeof(recv_msg) - 1, 0);
                if (recv_len == -1) {
                    perror("recv");
                    break;
                } else if (recv_len == 0) {
                    printf("Client said bye. Closing connection.\n");
                    break;
                }
                
                recv_msg[recv_len] = '\0'; // 确保字符串以空字符结尾
                printf("Recv: %s\n", recv_msg);
                int year = atoi(recv_msg);
                if (year > 0) {
                    const char* zodiac = getZodiac(year);
                    strcpy(send_msg, zodiac);
                    /* 发送消息 */
                    if (send(server_sock_data, send_msg, strlen(send_msg), 0) == -1) {
                        perror("send");
                        break;
                    }
                    printf("Send: %s\n", send_msg);
                }
            }

            /* 关闭数据socket */
            close(server_sock_data);
            exit(0); // 子进程退出
        } else { // 父进程
            if(close_socket_in_parent)
            close(server_sock_data); // 父进程不需要数据socket
        }
    }

    /* 关闭监听socket */
    close(server_sock_listen);

    return 0;
}